package com.briup.bookstore.web.interceptor;

import com.briup.bookstore.common.exception.ServiceException;
import com.briup.bookstore.common.response.ResultCode;
import com.briup.bookstore.common.security.SecurityContext;
import com.briup.bookstore.domain.bean.User;
import com.briup.bookstore.service.UserService;
import com.briup.bookstore.utils.JwtUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

/**
 * 登录认证的拦截器
 */
@Component
@RequiredArgsConstructor
public class AuthInterceptor implements HandlerInterceptor {

    private final UserService userService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 在真正处理请求之前获取 token，校验token是否存在及可用
        // 如果是Option请求，那么直接放行；因为Option请求是浏览器校验是否支持跨域时发送的预检请求，
        // 该请求中不会携带任何数据，同时除了支持跨域的响应头设置外，不会返回任何数据；所以可以直接放行
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            return true;
        }

        // 如果不是OPTIONS请求，那么需要进行校验
        String token = request.getHeader("token");
        Integer userId = JwtUtil.getInfo(token, "userId", Integer.class);
        User user = userService.queryById(userId);
        if (user == null) {
            throw new ServiceException(ResultCode.USER_STATUS_IS_FORBIDDEN);
        }
        SecurityContext.setCurrentUser(user);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 在最终处理完请求后，记得将当前线程对应的数据在ThreadLocal中清除，以此避免内存溢出
        SecurityContext.clear();
    }
}
